using Sandia.MVCFramework.Common;
using Sandia.MVCFramework.Data;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Sandia.MVCFramework.View
{
    /// <summary>
    /// Delegate used for when a views Minimized flag changes.
    /// </summary>
    /// <param name="minimized">Whether the view is minimized or not.</param>
    public delegate void OnMinimizedChanged(bool minimized);

    /// <summary>
    /// An abstract class that makes an IView into a control.
    /// </summary>
    public abstract class AbstractStandardView : UserControl, IView
    {
        /// <summary>
        /// Called when the view's Minimized flag changes.
        /// </summary>
        public event OnMinimizedChanged MinimizedChanged;

        /// <summary>
        /// The request router for this view
        /// </summary>
        private IRequestRouter viewRequestRouter;

        /// <summary>
        /// The IPublisher that will handle subscription requests for
        /// the view.
        /// </summary>
        private IPublisher viewPublisher;

        /// <summary>
        /// A boolean indicating whether the view is minimized or not.
        /// </summary>
        private bool minimized;

        /// <summary>
        /// The image for this view.
        /// </summary>
        private Image viewImage;

        /// <summary>
        /// The name of this view.
        /// </summary>
        private string viewName;

        /// <summary>
        /// The boolean indicating whether the view's
        /// toolbar will be visible.
        /// </summary>
        private bool toolBarVisible = true;

        /// <summary>
        /// The image for this view.
        /// </summary>
        protected Image image
        {
            get { return this.viewImage; }
            set { this.viewImage = value; }
        }

        /// <summary>
        /// The name of this view.
        /// </summary>
        protected string name
        {
            get { return this.viewName; }
            set { this.viewName = value; }
        }

        /// <summary>
        /// The IPublisher that will handle subscription requests for
        /// the view.
        /// </summary>
        protected IPublisher publisher
        {
            get { return this.viewPublisher; }
            set { this.viewPublisher = value; }
        }

        /// <summary>
        /// The request router for this view
        /// </summary>
        protected IRequestRouter requestRouter
        {
            get { return this.viewRequestRouter; }
            set { this.viewRequestRouter = value; }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="requestRouter">Request router for the view</param>
        /// <param name="publisher">Publisher for the view</param>
        protected AbstractStandardView(
            IRequestRouter requestRouter, 
            IPublisher publisher)
        {
            this.InitRequestGenerator(requestRouter);            
            this.publisher = publisher;
            this.setupView();
        }

        #region ISubscriber Members

        /// <summary>
        /// The list of IData types that this subscriber would like to subscribe
        /// to.
        /// </summary>
        public abstract IList<Type> DesiredSubscriptions
        {
            get;
        }

        /// <summary>
        /// Method for receiving and handling published data
        /// </summary>
        /// <param name="dataPacket">
        /// The data packet that was published.
        /// </param>
        public abstract void HandlePublishedData(
            DataPacket dataPacket);

        #endregion

        #region IView Members

        #region IRequestGenerator Members

        /// <summary>
        /// Initialize the request generator by telling
        /// it who routes the requests produced
        /// </summary>
        /// <param name="requestRouter">The router for requests
        /// generated</param>
        public void InitRequestGenerator(
            IRequestRouter requestRouter)
        {
            this.requestRouter = requestRouter;
        }

        #endregion

        /// <summary>
        /// Indicates whether the view is minimized or not.
        /// </summary>
        public bool Minimized
        {
            get
            {
                return this.minimized;
            }
            set
            {
                this.minimized = value;
                if (this.MinimizedChanged != null)
                {
                    this.MinimizedChanged(this.minimized);
                }
            }
        }

        /// <summary>
        /// A method to be implemented by inheriting classes for initializing
        /// the the view. This method should set the views name and image 
        /// parameters.
        /// </summary>
        protected abstract void setupView();

        /// <summary>
        /// The name for this view.
        /// </summary>
        public new string Name 
        {
            get { return this.name; }
        }

        /// <summary>
        /// The image for this view.
        /// </summary>
        public Image ViewImage
        {
            get
            {
                return this.image;
            }
        }

        /// <summary>
        /// Indicates whether or not the view will have a toolbar 
        /// visible in the view.
        /// </summary>
        public bool ToolBarVisible
        {
            get { return toolBarVisible; }
            set { toolBarVisible = value; }
        }

        #endregion

        #region IStartable Members

        /// <summary>
        /// Called when MVC Framework initialization has completed and
        /// transactions can begin.
        /// </summary>
        /// <remarks>
        /// IRequests and IData should not be sent before this method is called, 
        /// as this can cause race conditions while an application is 
        /// initializing.
        /// </remarks>
        public abstract void Start();

        #endregion
    }
}
